package ehsm

//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
// int EHSM_FFI_CALL(const char *reqJson, char *respJson) {
//       strcpy(respJson, "{\"code\":200,\"message\":\"ehsm error\",\"result\":{\"version\":\"v12.33\",\"git_sha\":\"fawefaefaefa\"}}");
//       printf("reqJson: %s\n",reqJson);
//       printf("respJson: %s",respJson);
//       return 0;
//}
import "C"
import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/zeebo/errs"
	"unsafe"
)

var Error = errs.Class("eHSM")

type RespIfc interface {
	Success() bool
	Error() error
}

type Req struct {
	Action  int `json:"action"`
	Payload any `json:"payload"`
}

type Resp struct {
	Code    int            `json:"code"`
	Message string         `json:"message"`
	Result  map[string]any `json:"result,omitempty"`
}

func (r *Resp) Success() bool {
	return r.Code == 200
}

func (r *Resp) Error() error {
	if r.Success() {
		return nil
	}
	if r.Message == "" {
		r.Message = "result error"
	}
	return errors.New(r.Message)
}

func eHsmCall(req string) (res string, err error) {
	cReq := C.CString(req)
	cRes := C.CString("")
	defer func() {
		C.free(unsafe.Pointer(cReq))
		C.free(unsafe.Pointer(cRes))
	}()
	ret := int(C.EHSM_FFI_CALL(cReq, cRes))
	if ret == 0 {
		res = C.GoString(cRes)
	} else {
		err = fmt.Errorf("eHsm call error[%d]", ret)
	}
	return
}

func EHsmCall(req any, res RespIfc) error {
	reqJson, err := json.Marshal(req)
	if err != nil {
		return Error.Wrap(err)
	}
	resJson, err := eHsmCall(string(reqJson))
	if err != nil {
		return Error.Wrap(err)
	}
	err = json.Unmarshal([]byte(resJson), &res)
	if err != nil {
		return Error.Wrap(err)
	}
	return nil
}

func EHsmCallResult(req any, res RespIfc) error {
	err := EHsmCall(req, res)
	if err != nil {
		return err
	}
	return Error.Wrap(res.Error())
}
